package com.bsj.travel.process.handle.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.bsj.consumerQ.function.HandleRun;
import com.bsj.travel.cached.redis.RedisCached;
import com.bsj.travel.config.rocketmq.producer.BaseMqPushUtil;
import com.bsj.travel.constant.BaseServerTopicConstants;
import com.bsj.travel.def.common.DTO.mqtt.MqttEvent;
import com.bsj.travel.def.common.DTO.mqtt.MqttEventPublish;
import com.bsj.travel.def.common.DTO.mqtt.business.NtpEventData;
import com.bsj.travel.def.common.DTO.mqtt.ota.down.DownOtaHttpInfo;
import com.bsj.travel.def.common.DTO.mqtt.ota.down.HttpOtaInfo;
import com.bsj.travel.def.common.DTO.mqtt.ota.up.UpOtaInfo;
import com.bsj.travel.def.common.VO.OtaUpgradeVO;
import com.bsj.travel.enums.MqttEventEnum;
import com.bsj.travel.process.config.PublicTopicConfig;
import com.bsj.travel.util.ExceptionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author yinhao
 * @version 1.0
 * @description 基础通信类数据处理具体实现
 * @date 2024/1/16
 */
@Service
@Slf4j
public class BasicTopicMessageHandleRun implements HandleRun {

    @Autowired
    private BaseMqPushUtil baseMqPushUtil;

    @Autowired
    private PublicTopicConfig topicConfig;

    @Autowired
    private RedisCached redisCached;

    @Override
    public void doRun(List<byte[]> list) {
        MqttEventPublish mqttEventPublish = new MqttEventPublish();
        long millis = System.currentTimeMillis();
        Map<String, List<UpOtaInfo>> otaMaps = new HashMap<>();
        for (byte[] bytes : list) {
            try {
                String message = new String(bytes);
                MqttEvent event = JSON.parseObject(message, MqttEvent.class);
                String client = event.getClient();
                String[] split = client.split("&");
                String productKey = split[1];
                String deviceName = split[0];
                MqttEventEnum eventEnum = MqttEventEnum.getMqttEventEnum(event.getEvent());
                switch (Objects.requireNonNull(eventEnum)) {
                    //OTA升级[基础通信类]
                    case OTA:
                        //设备上报OTA的版本信息
                        UpOtaInfo upOtaInfo = JSON.parseObject(event.getData().toString(), UpOtaInfo.class);
                        upOtaInfo.setProductKey(productKey);
                        upOtaInfo.setDeviceName(deviceName);
                        List<UpOtaInfo> upOtaInfos = otaMaps.get(productKey);
                        if (upOtaInfos == null) {
                            upOtaInfos = new ArrayList<>();
                        }
                        upOtaInfos.add(upOtaInfo);
                        otaMaps.put(productKey, upOtaInfos);
                        break;
                    //NTP时钟同步[基础通信类]
                    case NTP:
                        JSONObject jsonNtp = JSON.parseObject(event.getData().toString());
                        mqttEventPublish.setClient(event.getClient());
                        mqttEventPublish.setQos(event.getQos());
                        mqttEventPublish.setTopic(topicConfig.getPubTopic(MqttEventEnum.NTP.name(), productKey, deviceName));
                        NtpEventData ntpEventData = NtpEventData.builder()
                                .deviceSendTime(jsonNtp.getString("deviceSendTime"))
                                .serverSendTime(System.currentTimeMillis() + "")
                                .serverRecvTime(millis + "")
                                .build();
                        mqttEventPublish.setData(ntpEventData);
                        baseMqPushUtil.sendMqttMsgDownTag(mqttEventPublish);
                        break;
                    //影子[基础通信类]
                    case SHADOW:
                        //未实现
                        break;
                    default:
                        break;
                }
            } catch (Exception e) {
                log.error("基础通信类数据处理异常: {}", ExceptionUtil.getStackStr(e));
                continue;
            }
        }
        //处理OTA消息包内容
        handleOtaUp(otaMaps, topicConfig, baseMqPushUtil, redisCached);
    }

    private static void handleOtaUp(Map<String, List<UpOtaInfo>> otaMaps,
                                    PublicTopicConfig topicConfig,
                                    BaseMqPushUtil baseMqPushUtil,
                                    RedisCached redisCached) {
        if (!otaMaps.isEmpty()) {
            //TODO 需要从redis 中获取OTA升级信息
            List<OtaUpgradeVO> otaUpgrades = new ArrayList<>();

            Map<String, OtaUpgradeVO> productOtaMap = otaUpgrades.stream().filter(item -> item.getIsDisable() == 2)
                    .collect(Collectors.toMap(OtaUpgradeVO::getName, a -> a, (k1, k2) -> k1));
            Iterator<Map.Entry<String, List<UpOtaInfo>>> iterator = otaMaps.entrySet().iterator();
            while (iterator.hasNext()) {
                Map.Entry<String, List<UpOtaInfo>> next = iterator.next();
                String key = next.getKey();
                List<UpOtaInfo> value = next.getValue();
                OtaUpgradeVO otaUpgradeVO = productOtaMap.get(key);
                if (otaUpgradeVO == null) {
                    continue;
                }
                value.stream().forEach(v -> {
                    //如果有需要升级的OTA包，则进行下发
                    HttpOtaInfo httpOtaInfo = new HttpOtaInfo();
                    httpOtaInfo.fillData(otaUpgradeVO);
                    DownOtaHttpInfo otaHttpInfo = DownOtaHttpInfo.builder()
                            .code("1000")
                            .message("success")
                            .id(System.currentTimeMillis())
                            .data(httpOtaInfo)
                            .build();
                    MqttEventPublish mqttEventPublish = new MqttEventPublish();
                    String client = v.getDeviceName() + "&" + v.getProductKey();
                    mqttEventPublish.setClient(client);
                    mqttEventPublish.setQos(0);
                    mqttEventPublish.setTopic(topicConfig.getPubTopic(MqttEventEnum.OTA.name(), v.getProductKey(), v.getDeviceName()));
                    mqttEventPublish.setData(otaHttpInfo);
                    //消息下行
                    baseMqPushUtil.sendMqttMsgDownTag(mqttEventPublish);
                });
            }
        }
    }
}
